连接关闭与 TIME_WAIT(进阶)
复习
- 三次握手:建立连接时同步双方状态
- 序号与确认:双方各自维护收发进度
- TCP 为什么需要连接:连接是双方的共同状态
本章为进阶内容,零基础读者可以跳过,不影响后续阅读。
TL;DR
- 关闭连接也要有约定步骤,不能单方面说停就停
- 通常需要四次挥手,因为两个方向要分别关闭
- TIME_WAIT 让主动关闭方多等一会儿再真正消失
- 等待是为了确认对方收到关闭确认,并让旧包消散
正文
有始就有终。连接建立是三次握手,那结束呢?总不能一方说“我不说了”,就单方面把连接撕掉吧——另一方可能还在发数据呢。
所以,关闭连接同样需要双方商量着来,这叫四次挥手。
为什么是四次
因为 TCP 连接是双向的:你到我这有一条数据通道,我到你也有一条。要彻底关闭,得两个方向各自关门。
过程大致是:
- 一方发 FIN:“我这边没有数据要发了。”
- 另一方回 ACK:“知道了。”
- 等另一方也把数据发完,再发一个 FIN:“我这边也发完了。”
- 最先的一方再回 ACK:“收到,连接关闭。”
FIN 和 ACK 一来一回,两个方向各一次,加起来就是四次。这也解释了一个现象:半关闭——某一方已经发完,另一方却还能继续发。
对比一下:建立时为什么三次就够?因为“我要连你”和“我同意”可以合并成一步(SYN+ACK);而关闭时,对方未必立刻也想关,ACK 和它自己的 FIN 之间隔着“它还有没有话要说”,所以通常拆成两步。需要几次,取决于双方状态能不能合并。
TIME_WAIT:多等一会儿
主动关闭连接的那一方,在发出最后一个 ACK 后,并不会立刻消失,而是进入一个叫 TIME_WAIT 的状态,静静等待一段时间(通常是两倍的最长报文寿命)。
为什么要等?主要有两个原因:
- 确保对方收到最后的 ACK。这个 ACK 万一丢了,对方会重发 FIN。此时如果自己已经消失,对方就会一直等不到回应。多待一会儿,就能接到重发的 FIN 并再次确认
- 让本次连接的旧数据包在网络中消散。如果立刻用相同的地址和端口建立新连接,网络上残留的旧包可能被误当成新连接的数据,造成混乱
等这段时间过去,旧包已经陈旧到不会再被送达,新连接才安全。
这提醒我们:“结束”往往比“开始”更需要小心。 开始出错,大不了重来;结束出错,却可能留下收尾没做干净的麻烦。
思考题 1
为什么关闭连接通常要四次挥手,而建立连接三次就够?
思考题 2
TIME_WAIT 的状态,是为了解决哪两个问题?
小结
知识点
- 关闭连接需要双向分别关闭,通常四次挥手
- 建立时可合并 SYN 与 ACK,故只需三次
- 主动关闭方进入 TIME_WAIT 等待
- 等待可确保最后 ACK 被处理,并让旧包消散
参考资料
- Wikipedia(zh):传输控制协议:连接关闭与状态迁移
- Wikipedia(zh):TIME_WAIT:主动关闭连接后的等待状态
思考题答案(仅供参考)
思考题 1
因为关闭时两个方向要各自关一次,且对方的 ACK 与它自己的 FIN 之间可能隔着“还有数据要发”,难以合并,所以通常需要四次。建立时“我想连”和“我同意”可以合进一个 SYN+ACK,故三次即可。
思考题 2
一是确保最后那个 ACK 即使丢失,自己也能收到对方重发的 FIN 并再次确认;二是让本次连接的残留数据包在网络中彻底消散,避免它们被误当成之后同地址端口新连接的数据。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图

设计师 | 南国微雪